package com.fjh.module.rbac.controller.monitor;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
import java.util.Set;

import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import com.baomidou.mybatisplus.extension.plugins.pagination.PageDTO;
import com.fjh.common.annotation.Log;
import com.fjh.common.constant.CacheConstants;
import com.fjh.common.controller.BaseController;
import com.fjh.common.enums.BusinessType;
import com.fjh.common.redis.RedisCache;
import com.fjh.common.utils.StringUtils;
import com.fjh.module.rbac.pojo.AjaxResult;
import com.fjh.module.rbac.pojo.CustomPage;
import com.fjh.module.rbac.pojo.SysUserOnline;
import com.fjh.module.rbac.service.ISysUserOnlineService;
import com.fjh.security.easy.starter.userdetails.CustomUser;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.security.core.context.SecurityContextImpl;
import org.springframework.session.data.redis.RedisSessionRepository;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

/**
 * 在线用户监控
 *
 * @author ruoyi
 */
@RestController
@RequestMapping("/monitor/online")
public class SysUserOnlineController extends BaseController {

    @Autowired
    private ISysUserOnlineService userOnlineService;

    @Autowired
    private RedisCache redisCache;

//    @Autowired
//    private RedisTemplate<String, String> redisTemplate;

    @Autowired
    private RedisSessionRepository sessionRepository;


    @PreAuthorize("@ss.hasPermi('monitor:online:list')")
    @GetMapping("/list")
    public PageDTO<SysUserOnline> list(CustomPage page, String ipaddr, String userName) {
//        Collection<String> keys = redisCache.keys(CacheConstants.LOGIN_TOKEN_KEY + "*");
//        Set<String> keys = redisTemplate.keys(CacheConstants.LOGIN_TOKEN_KEY + "*");
        List<SysUserOnline> userOnlineList = queryOnlineUsers();
//        if (CollectionUtils.isEmpty(keys)) {
//            return toPageDTO(userOnlineList, null);
//        }
//        for (String key : keys) {
//            LoginUser user = redisCache.getCacheObject(key);
//            if (StringUtils.isNotEmpty(ipaddr) && StringUtils.isNotEmpty(userName)) {
//                userOnlineList.add(userOnlineService.selectOnlineByInfo(ipaddr, userName, user));
//            } else if (StringUtils.isNotEmpty(ipaddr)) {
//                userOnlineList.add(userOnlineService.selectOnlineByIpaddr(ipaddr, user));
//            } else if (StringUtils.isNotEmpty(userName) && StringUtils.isNotNull(user.getUser())) {
//                userOnlineList.add(userOnlineService.selectOnlineByUserName(userName, user));
//            } else {
//                userOnlineList.add(userOnlineService.loginUserToUserOnline(user));
//            }
//        }
//        Collections.reverse(userOnlineList);
//        userOnlineList.removeAll(Collections.singleton(null));
        CustomPage customPage = new CustomPage();
        customPage.setPageNum(1);
        customPage.setPageSize(10);
        customPage.setTotal(userOnlineList.size());
        return toPageDTO(userOnlineList, customPage);
    }

    /**
     * 查询当前在线的所有用户。通过查询Redis中所有未过期的Session信息实现。
     * 查询字段（username、nickname、userCode、hostAddress、lastAccessedTime、maxInactiveInterval、creationTime等）
     */
    public List<SysUserOnline> queryOnlineUsers() {
        // 获取所有存储会话的键，并根据需要进行过滤和处理
        Set<String> keys = sessionRepository.getSessionRedisOperations()
            .keys("spring:session:sessions:*");
        List<SysUserOnline> list = new ArrayList<>();
        Object[] arr = {"lastAccessedTime", "maxInactiveInterval", "creationTime",
            "sessionAttr:SPRING_SECURITY_CONTEXT"};
        keys.stream().forEach(item -> {
            if (((String) item).indexOf("expires") == -1) {//排除过期信息
                List<Object> values = sessionRepository.getSessionRedisOperations().opsForHash()
                    .multiGet(item, Arrays.asList(arr));
//                Map<String, Object> re = new HashMap<>();
//                re.put("lastAccessedTime",values.get(0));
//                re.put("maxInactiveInterval",values.get(1));
//                re.put("creationTime",values.get(2));
//                re.put("sessionId",parseUserToken((String)item));
                SysUserOnline sysUserOnline = new SysUserOnline();
                sysUserOnline.setLoginTime((Long) values.get(2));
                sysUserOnline.setTokenId(parseUserToken((String)item));
                this.parseUserInfo(values.get(3), sysUserOnline);
                if(Objects.nonNull(sysUserOnline.getUserName())){
                    list.add(sysUserOnline);
                }
            }
        });
        return list;
    }

    /**
     * 根据Redis中存储对象的Key解析对应的SessionId
     */
    private String parseUserToken(String key) {
        if (StringUtils.isNotEmpty(key)) {
            String[] arr = key.split(":");
            if (arr != null && arr.length == 4) {
                return arr[3];
            }
        }
        return null;
    }

    /**
     * 解析Redis中存储的用户信息和登录信息
     */
    private void parseUserInfo(Object val,  SysUserOnline sysUserOnline) {
        if (val != null && val instanceof SecurityContextImpl) {
            JSONObject json = (JSONObject) JSON.toJSON(val);
            if (json != null && json.containsKey("authentication")) {
                JSONObject authInfo = json.getJSONObject("authentication");
                if (authInfo != null) {
                    if (authInfo.containsKey("name")) {//用户登录名称
                        sysUserOnline.setUserName(authInfo.getString("name"));
                    }
                    if (authInfo.containsKey("details")) {//用户登录时的地址
                        JSONObject details = authInfo.getJSONObject("details");
                        if (details != null && details.containsKey("remoteAddress")) {
                            sysUserOnline.setIpaddr(details.getString("remoteAddress"));
                        }
                    }
                    if (authInfo.containsKey("principal")) {
                        CustomUser customUser = authInfo.getObject("principal", CustomUser.class);
                        sysUserOnline.setUserName(customUser.getUsername());
                    }
                }
            }
        }
    }


    /**
     * 强退用户
     */
    @PreAuthorize("@ss.hasPermi('monitor:online:forceLogout')")
    @Log(title = "在线用户", businessType = BusinessType.FORCE)
    @DeleteMapping("/{tokenId}")
    public AjaxResult forceLogout(@PathVariable String tokenId) {
//        redisTemplate.delete(CacheConstants.LOGIN_TOKEN_KEY + tokenId);
        sessionRepository.deleteById(tokenId);
        return success();
    }
}
